package com.noobyang.share;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {

    public static List<ServerThread> connections = new ArrayList<ServerThread>();

    public static void main(String[] args) {
        try {
            // 1.创建一个服务器端Socket，即ServerSocket，指定绑定的端口，并监听此端口
            ServerSocket serverSocket = new ServerSocket(8888);
            Socket socket = null;
            // 记录客户端的数量
            int count = 0;
            System.out.println("1. Server start");

            // 循环监听等待客户端的连接
            while (true) {
                // 调用accept()方法开始监听，等待客户端的连接
                socket = serverSocket.accept();

                ServerThread serverThread = new ServerThread(socket);
                serverThread.start();

                connections.add(serverThread);
                count++;// 统计客户端的数量
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static class ServerThread extends Thread {

        private Socket socket = null;

        public String ip;
        public int port;

        private BufferedReader bufferedReader = null;
        private OutputStreamWriter outputStreamWriter = null;

        public ServerThread(Socket socket) throws IOException {
            this.socket = socket;
            this.bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.outputStreamWriter = new OutputStreamWriter(socket.getOutputStream());
        }

        // 线程执行的操作，响应客户端的请求
        public void run() {
            InetAddress address = socket.getInetAddress();
            ip = address.getHostAddress();
            port = socket.getPort();
            System.out.println("2. Server Client connect: " + address.getHostAddress() + ": " + socket.getPort());
            System.out.println("2. Server Client connect: " + Server.connections);

            try {
                StringBuilder temp = new StringBuilder(toString() + ";");
                for (ServerThread serverThread : Server.connections) {
                    if (!serverThread.ip.equals(ip) || serverThread.port != port) {
                        temp.append(serverThread.toString());
                    }
                }
                outputStreamWriter.write(temp.toString() + "\n");
                outputStreamWriter.flush();
                System.out.println("2. Server Client send: " + temp.toString());

                // 获取输入流，并读取客户端信息
                String info = null;
                while ((info = bufferedReader.readLine()) != null) {
                    // 循环读取客户端的信息
                    System.out.println("3. Server Client say: " + info);

                    if (info.startsWith("connect")) {
                        //接收到穿透消息，通知目标节点
                        String[] infos = info.split("_");
                        //目标节点的外网ip地址
                        String ip = infos[1];
                        //目标节点的外网端口
                        String port = infos[2];

                        System.out.println("4. Server NAT to " + ip + ":" + port);

                        for (ServerThread server : Server.connections) {
                            if (server.socket.getInetAddress().getHostAddress().equals(ip)
                                    && server.socket.getPort() == Integer.parseInt(port)) {

                                //发送命令通知目标节点进行穿透连接
                                server.outputStreamWriter.write("autoConnect_" + socket.getInetAddress().getHostAddress() + "_" + socket.getPort()
                                        + "\n");
                                server.outputStreamWriter.flush();

                                break;
                            }
                        }
                    } else {
                        // 获取输出流，响应客户端的请求
                        outputStreamWriter.write("Welcome " + info + "\n");
                        // 调用flush()方法将缓冲输出
                        outputStreamWriter.flush();
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                Server.connections.remove(this);
                // 关闭资源
                try {
                    if (bufferedReader != null) {
                        bufferedReader.close();
                    }
                    if (outputStreamWriter != null) {
                        outputStreamWriter.close();
                    }
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public String toString() {
            return ip + "_" + port;
        }

    }
}
